package com.hopechart.micro.domain.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.hopechart.micro.common.exception.BusinessException;
import com.hopechart.micro.common.exception.ErrorCode;
import com.hopechart.micro.common.generator.mapper.MyMapper;
import com.hopechart.micro.domain.service.IBaseService;
import org.apache.commons.beanutils.PropertyUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import tk.mybatis.mapper.entity.Example;

import java.util.List;
import java.util.Map;

/**
 * @author daijiang@hopechart.com
 */
public abstract class BaseServiceImpl<T> implements IBaseService<T> {

	/**
	 * 获取Mapper实例
	 * 
	 * @return
	 */
	public abstract MyMapper<T> getMapper();

	private Logger LOGGER = LoggerFactory.getLogger(BaseServiceImpl.class);

	@Override
	public int insert(T entity) throws BusinessException {
		try {
			return getMapper().insert(entity);
		} catch (Exception e) {
			LOGGER.error(ErrorCode.DB_INSERT.getMessage(), e);
			throw new BusinessException(ErrorCode.DB_INSERT, e.getMessage(), e);
		}
	}

	@Override
	public int insertSelective(T entity) throws BusinessException {
		try {
			return getMapper().insertSelective(entity);
		} catch (Exception e) {
			LOGGER.error(ErrorCode.DB_INSERT.getMessage(), e);
			throw new BusinessException(ErrorCode.DB_INSERT, e.getMessage(), e);
		}
	}

	@Override
	public int insertList(List<T> entities) throws BusinessException {
		try {
			return getMapper().insertList(entities);
		} catch (Exception e) {
			LOGGER.error(ErrorCode.DB_INSERT.getMessage(), e);
			throw new BusinessException(ErrorCode.DB_INSERT, e.getMessage(), e);
		}
	}

	@Override
	public int save(T entity) throws BusinessException {
		try {
			int count = this.insertSelective(entity);
			return count;
		} catch (Exception e) {
			LOGGER.error(ErrorCode.DB_INSERT.getMessage(), e);
			throw new BusinessException(ErrorCode.DB_INSERT, e.getMessage(), e);
		}
	}

	@Override
	public int deleteByExample(Object example) throws BusinessException {
		try {
			return getMapper().deleteByExample(example);
		} catch (Exception e) {
			LOGGER.error(ErrorCode.DB_DELETE.getMessage(), e);
			throw new BusinessException(ErrorCode.DB_DELETE, e.getMessage(), e);
		}
	}

	@Override
	public int delete(T entity) throws BusinessException {
		try {
			return getMapper().delete(entity);
		} catch (Exception e) {
			LOGGER.error(ErrorCode.DB_DELETE.getMessage(), e);
			throw new BusinessException(ErrorCode.DB_DELETE, e.getMessage(), e);
		}
	}

	@Override
	public int deleteByPrimaryKey(Object key) throws BusinessException {
		try {
			return getMapper().deleteByPrimaryKey(key);
		} catch (Exception e) {
			LOGGER.error(ErrorCode.DB_DELETE.getMessage(), e);
			throw new BusinessException(ErrorCode.DB_DELETE, e.getMessage(), e);
		}
	}

	@Override
	public int deleteByIds(String ids) throws BusinessException {
		return 0;
	}

	@Override
	public int updateByPrimaryKey(T entity) throws BusinessException {
		try {
			return getMapper().updateByPrimaryKey(entity);
		} catch (Exception e) {
			LOGGER.error(ErrorCode.DB_UPDATE.getMessage(), e);
			throw new BusinessException(ErrorCode.DB_UPDATE, e.getMessage(), e);
		}
	}

	@Override
	public int updateByPrimaryKeySelective(T entity) throws BusinessException {
		try {
			return getMapper().updateByPrimaryKeySelective(entity);
		} catch (Exception e) {
			LOGGER.error(ErrorCode.DB_UPDATE.getMessage(), e);
			throw new BusinessException(ErrorCode.DB_UPDATE, e.getMessage(), e);
		}
	}

	@Override
	public int updateAll(T entity) throws BusinessException {
		try {
			return getMapper().updateByPrimaryKeySelective(entity);
		} catch (Exception e) {
			LOGGER.error(ErrorCode.DB_UPDATE.getMessage(), e);
			throw new BusinessException(ErrorCode.DB_UPDATE, e.getMessage(), e);
		}
	}

	@Override
	public int updateNotNull(T entity) throws BusinessException {
		try {
			return getMapper().updateByPrimaryKeySelective(entity);
		} catch (Exception e) {
			LOGGER.error(ErrorCode.DB_UPDATE.getMessage(), e);
			throw new BusinessException(ErrorCode.DB_UPDATE, e.getMessage(), e);
		}
	}

	@Override
	public int updateByExample(Example example, T entity) throws BusinessException {
		try {
			return getMapper().updateByExampleSelective(entity, example);
		} catch (Exception e) {
			LOGGER.error(ErrorCode.DB_UPDATE.getMessage(), e);
			throw new BusinessException(ErrorCode.DB_UPDATE, e.getMessage(), e);
		}
	}

	@Override
	public int selectCount(T entity) throws BusinessException {
		try {
			return getMapper().selectCount(entity);
		} catch (Exception e) {
			LOGGER.error(ErrorCode.DB_QUERY.getMessage(), e);
			throw new BusinessException(ErrorCode.DB_QUERY, e.getMessage(), e);
		}
	}

	@Override
	public int selectCountByExample(Example example) throws BusinessException {
		try {
			return getMapper().selectCountByExample(example);
		} catch (Exception e) {
			LOGGER.error(ErrorCode.DB_QUERY.getMessage(), e);
			throw new BusinessException(ErrorCode.DB_QUERY, e.getMessage(), e);
		}
	}

	@Override
	public List<T> select(T entity) throws BusinessException {
		try {
			return getMapper().select(entity);
		} catch (Exception e) {
			LOGGER.error(ErrorCode.DB_QUERY.getMessage(), e);
			throw new BusinessException(ErrorCode.DB_QUERY, e.getMessage(), e);
		}
	}

	@Override
	public T selectByPrimaryKey(Object key) throws BusinessException {
		try {
			return getMapper().selectByPrimaryKey(key);
		} catch (Exception e) {
			LOGGER.error(ErrorCode.DB_QUERY.getMessage(), e);
			throw new BusinessException(ErrorCode.DB_QUERY, e.getMessage(), e);
		}
	}

	@Override
	public PageInfo<T> selectPage(int pageNum, int pageSize) throws BusinessException {
		try {
			return selectPage(pageNum, pageSize, null, null);
		} catch (Exception e) {
			LOGGER.error(ErrorCode.DB_QUERY.getMessage(), e);
			throw new BusinessException(ErrorCode.DB_QUERY, e.getMessage(), e);
		}
	}

	@Override
	public PageInfo<T> selectPage(int pageNum, int pageSize, T entity) throws BusinessException {
		try {
			if (null == entity) {
				return selectPage(pageNum, pageSize);
			} else {
				return selectPage(pageNum, pageSize, entity, null);
			}

		} catch (Exception e) {
			LOGGER.error(ErrorCode.DB_QUERY.getMessage(), e);
			throw new BusinessException(ErrorCode.DB_QUERY, e.getMessage(), e);
		}
	}

	@Override
	public PageInfo<T> selectPage(int pageNum, int pageSize, T entity, String orderSqlStr) throws BusinessException {
		try {
			List<T> list;
			Example example = null;
			if (null != entity) {
				example = new Example(entity.getClass(), false, false);
				Example.Criteria criteria = example.createCriteria();
				Map<String, Object> map = PropertyUtils.describe(entity);

				for (Map.Entry<String, Object> entry : map.entrySet()) {
					if (entry.getValue() == null || "".equals(entry.getValue())) {
						continue;
					}
					criteria.andEqualTo(entry.getKey(), entry.getValue());
				}

				if (null != orderSqlStr && "".equals(orderSqlStr)) {
					example.setOrderByClause(orderSqlStr);
				}

				PageHelper.startPage(pageNum, pageSize);
			}

			list = getMapper().selectByExample(example);

			return new PageInfo<T>(list);
		} catch (Exception e) {
			LOGGER.error(ErrorCode.DB_QUERY.getMessage(), e);
			throw new BusinessException(ErrorCode.DB_QUERY, e.getMessage(), e);
		}
	}

	@Override
	public List<T> select(T entity, String orderSqlStr) throws BusinessException {
		try {
			Example example = null;
			if (null != entity) {
				example = new Example(entity.getClass(), false, false);
				Example.Criteria criteria = example.createCriteria();
				Map<String, Object> map = PropertyUtils.describe(entity);

				for (Map.Entry<String, Object> entry : map.entrySet()) {
					if (entry.getValue() == null || "".equals(entry.getValue())) {
						continue;
					}
					criteria.andEqualTo(entry.getKey(), entry.getValue());
				}

				if (null != orderSqlStr && "".equals(orderSqlStr)) {
					example.setOrderByClause(orderSqlStr);
				}
			}

			return getMapper().selectByExample(example);
		} catch (Exception e) {
			LOGGER.error(ErrorCode.DB_QUERY.getMessage(), e);
			throw new BusinessException(ErrorCode.DB_QUERY, e.getMessage(), e);
		}
	}

	@Override
	public T selectOne(T entity) throws BusinessException {
		try {
			List<T> results = getMapper().select(entity);
			if (results != null && results.size() > 0) {
				return results.get(0);
			} else {
				return null;
			}
		} catch (Exception e) {
			LOGGER.error(ErrorCode.DB_QUERY.getMessage(), e);
			throw new BusinessException(ErrorCode.DB_QUERY, e.getMessage(), e);
		}
	}

	@Override
	public List<T> selectByIds(String ids) throws BusinessException {
		// TODO 自定义Mapper 集成 SeniorMapper 重写该方法
		return null;
	}

	@Override
	public T selectByKey(Object key) throws BusinessException {
		try {
			if (null == key) {
				return null;
			}
			return getMapper().selectByPrimaryKey(key);
		} catch (Exception e) {
			LOGGER.error(ErrorCode.DB_QUERY.getMessage(), e);
			throw new BusinessException(ErrorCode.DB_QUERY, e.getMessage(), e);
		}
	}

	@Override
	public List<T> selectByExample(Example example) throws BusinessException {
		try {
			return getMapper().selectByExample(example);
		} catch (Exception e) {
			LOGGER.error(ErrorCode.DB_QUERY.getMessage(), e);
			throw new BusinessException(ErrorCode.DB_QUERY, e.getMessage(), e);
		}
	}

	@Override
	public List<T> selectAllEntities() throws BusinessException {
		try {
			return getMapper().selectByExample(null);
		} catch (Exception e) {
			LOGGER.error(ErrorCode.DB_QUERY.getMessage(), e);
			throw new BusinessException(ErrorCode.DB_QUERY, e.getMessage(), e);
		}
	}

	@Override
	public PageInfo<T> selectPagingByExample(Object example, int pageNum, int pageSize) throws BusinessException {
		try {
			PageHelper.startPage(pageNum, pageSize);
			List<T> dataList = getMapper().selectByExample(example);
			return new PageInfo<T>(dataList);
		} catch (Exception e) {
			LOGGER.error(ErrorCode.DB_QUERY.getMessage(), e);
			throw new BusinessException(ErrorCode.DB_QUERY, e.getMessage(), e);
		}
	}
}
